﻿/*
Copyright (c) 2010 <a href="http://www.gutgames.com">James Craig</a>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.*/
using System;
using System.Data;
using System.Deployment.Application;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Windows.Forms;
using SGLLv2.UI.DataSetSGLLTableAdapters;
using SGLLv2.UI.Properties;
using System.Security.Cryptography;

namespace SGLLv2.UI
{
    static class Utilities
    {
        /// <summary>
        /// Reports to the Developer the exception in order to take action
        /// </summary>
        /// <param name="exception">The exception to be reported</param>
        public static void ExceptionManager(Exception exception)
        {
            try
            {
                SendMail(Settings.Default.DeveloperEmail, Settings.Default.ErrorEmailSubject, String.Format(SGLLv2.UI.Properties.Resources.ErrorReportHtml, DateTime.Now, Environment.MachineName, ApplicationDeployment.IsNetworkDeployed ? ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString() : Settings.Default.AppDevVersion, Environment.UserName, exception.Message, exception.Source, exception.TargetSite, exception.StackTrace));
            }
            catch (Exception)
            {
                
                throw;
            }
            
        }
        /// <summary>
        /// Send a email
        /// </summary>
        /// <param name="subject">Context of the mail </param>
        /// <param name="body">Message</param>
        /// <param name="to">Email Address </param>
        public static void SendMail(string to, string subject, string body)
        {
            try
            {
                // Declare Local Variables
                SETTINGS_LASTESTTableAdapter settingsLastestTableAdapter = new SETTINGS_LASTESTTableAdapter();
             
                // Get Data
                DataTable dataTable = settingsLastestTableAdapter.GetData();

                // Validations
                if (dataTable.Rows[0][0] == DBNull.Value) throw new Exception(Resources.MessageErrorEmailRequied);
                if (dataTable.Rows[0][1] == DBNull.Value) throw new Exception(Resources.MessageErrorPasswordRequied);
                
                // Coding
                MailMessage message = new MailMessage { From = new MailAddress(Decrypt(((DataSetSGLL.SETTINGS_LASTESTRow)dataTable.Rows[0]).EMAIL), Settings.Default.CompanyName) };
                message.To.Add(new MailAddress(to));
                message.Subject = subject;
                message.Body = body;
                message.IsBodyHtml = true;
                SmtpClient client = new SmtpClient(Settings.Default.SMTPServer)
                {
                    EnableSsl = true,
                    UseDefaultCredentials = false,
                    Credentials = new NetworkCredential(Decrypt(((DataSetSGLL.SETTINGS_LASTESTRow)dataTable.Rows[0]).EMAIL), Decrypt(((DataSetSGLL.SETTINGS_LASTESTRow)dataTable.Rows[0]).PASSWORD))
                };
                client.Send(message);

                // Let the user know if the message was send correctly.
                MessageBox.Show(Resources.MessageSuccessfulErrorReportEmail, Settings.Default.AppShortName, MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
            }
            catch (Exception exception)
            {
                MessageBox.Show(String.Concat(exception.Message, Environment.NewLine, exception.InnerException.Message, Environment.NewLine, Resources.MessageErrorSendingReportEmail), Settings.Default.AppShortName, MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
            }
        }
        /// <summary>
        /// Encrypts a string with AES256
        /// </summary>
        /// <param name="PlainText">Text to be encrypted</param>
        /// <param name="Password">Password to encrypt with</param>
        /// <param name="Salt">Salt to encrypt with</param>
        /// <param name="HashAlgorithm">Can be either SHA1 or MD5</param>
        /// <param name="PasswordIterations">Number of iterations to do</param>
        /// <param name="InitialVector">Needs to be 16 ASCII characters long</param>
        /// <param name="KeySize">Can be 128, 192, or 256</param>
        /// <returns>An encrypted string</returns>
        public static string Encrypt(string PlainText, string Password = "Medipath", string Salt = "SGLL", string HashAlgorithm = "SHA1", int PasswordIterations = 2, string InitialVector = "7P@0ex`(E'R;y.U#", int KeySize = 256)
        {
            if (string.IsNullOrEmpty(PlainText)) return string.Empty;
            var InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
            var SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
            var PlainTextBytes = Encoding.UTF8.GetBytes(PlainText);
            var DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);
            var KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
            var SymmetricKey = new RijndaelManaged { Mode = CipherMode.CBC };
            byte[] CipherTextBytes;
            using (var Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes))
            {
                using (var MemStream = new MemoryStream())
                {
                    using (var CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write))
                    {
                        CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
                        CryptoStream.FlushFinalBlock();
                        CipherTextBytes = MemStream.ToArray();
                        MemStream.Close();
                        CryptoStream.Close();
                    }
                }
            }
            SymmetricKey.Clear();
            return Convert.ToBase64String(CipherTextBytes);
        }
        /// <summary>
        /// Decrypts a string encrypted with AES256
        /// </summary>
        /// <param name="CipherText">Text to be decrypted</param>
        /// <param name="Password">Password to decrypt with</param>
        /// <param name="Salt">Salt to decrypt with</param>
        /// <param name="HashAlgorithm">Can be either SHA1 or MD5</param>
        /// <param name="PasswordIterations">Number of iterations to do</param>
        /// <param name="InitialVector">Needs to be 16 ASCII characters long</param>
        /// <param name="KeySize">Can be 128, 192, or 256</param>
        /// <returns>A decrypted string</returns>
        public static string Decrypt(string CipherText, string Password = "Medipath", string Salt = "SGLL", string HashAlgorithm = "SHA1", int PasswordIterations = 2, string InitialVector = "7P@0ex`(E'R;y.U#", int KeySize = 256)
        {
            if (string.IsNullOrEmpty(CipherText)) return string.Empty;
            var InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
            var SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
            var CipherTextBytes = Convert.FromBase64String(CipherText);
            var DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);
            var KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
            var SymmetricKey = new RijndaelManaged { Mode = CipherMode.CBC };
            var PlainTextBytes = new byte[CipherTextBytes.Length];
            int ByteCount;
            using (var Decryptor = SymmetricKey.CreateDecryptor(KeyBytes, InitialVectorBytes))
            {
                using (var MemStream = new MemoryStream(CipherTextBytes))
                {
                    using (var CryptoStream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read))
                    {
                        ByteCount = CryptoStream.Read(PlainTextBytes, 0, PlainTextBytes.Length);
                        MemStream.Close();
                        CryptoStream.Close();
                    }
                }
            }
            SymmetricKey.Clear();
            return Encoding.UTF8.GetString(PlainTextBytes, 0, ByteCount);
        }
    }
}